package xml.resource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
import org.restlet.resource.ResourceException;
import xml.hcard.HCARDFactory;
import xml.hcard.RemoteHCARDFactory;
import xml.model.Promotion;
import xml.validator.LengthValidator;
import xml.validator.LongRangeValidator;
import xml.validator.NotEmptyValidator;
import xml.validator.URIValidator;

/**
 * Resource représentant une promotion
 * Méthodes: GET, PUT, DELETE
 * @author marya
 */
public class PromotionResource extends AbstractResource {

    private Promotion promotion;

    public PromotionResource() {
        super();
    }

    @Override
    protected void doInit() throws ResourceException {
        Long idPromotion;
        final String sqlPromotion = "SELECT * FROM groupe WHERE id_groupe = ";
        String idPromotionAttribute = getRequest().getAttributes().get("idPromotion").toString();
        System.out.println("INIT: " + idPromotionAttribute);
        LongRangeValidator longRangeValidator = new LongRangeValidator(1l, null);
        Connection connexion = null;
        //Validation de l'id de la promotion
        if (longRangeValidator.isValid(idPromotionAttribute)) {
            idPromotion = Long.parseLong(idPromotionAttribute);
        } else {
            errors.add(new ResourceError("invalidPromotion"));
            throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST);
        }
        try {
            connexion = database.getNewConnection();
            Statement statement = connexion.createStatement();

            ResultSet rs = statement.executeQuery(sqlPromotion + idPromotion);
            if (!rs.next()) {
                setExisting(false);
            } else {
                promotion = new Promotion(rs.getInt("id_groupe"), rs.getString("nom"), null);
                if (rs.getString("url") == null) {
                    throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Bad request to attempt groups");
                } else {
                    promotion.setUri(getRootRef().getHostIdentifier() + "/promotions/" + promotion.getIdGroupe());
                }
            }
            connexion.close();

        } catch (SQLException e) {
            DbUtils.closeQuietly(connexion);
            throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e);
        }


    }

    @Get
    public Representation doGet() throws Exception {
        Representation response = null;
        System.out.println("GET: " + promotion);
        final String sqlPromotion = "SELECT url FROM groupe WHERE id_groupe = " + promotion.getIdGroupe();
        Connection connexion = null;
        ResultSet rs = null;
        try {
            connexion = database.getNewConnection();
            rs = connexion.createStatement().executeQuery(sqlPromotion);
            rs.next();
            HCARDFactory hF = new RemoteHCARDFactory(rs.getString("url"));
            response = hF.start().toXML();
            connexion.close();
        } catch (SQLException e) {
            DbUtils.closeQuietly(connexion);
            DbUtils.closeQuietly(rs);
            throw e;
        }

        return response;
    }

    @Put
    public Representation doPut(Representation entity) throws Exception {
        Representation response = null;
        xml.form.Form form = getNewForm(entity);
        final String sqlPromotion = "UPDATE groupe SET nom = ?, url = ? WHERE id_groupe = " + promotion.getIdGroupe();
        Connection connexion = null;

        //Mettre ici un formulaire validable à implémenter
        try {
            if (!form.isValid()) {
                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                for (String error : form.getMessages()) {
                    errors.add(new ResourceError(error));
                }
            } else {
                String url = form.getFirstValue("uriPromotion");
                String nom = form.getFirstValue("nomPromotion");
                HCARDFactory hF = new RemoteHCARDFactory(url);

                if (hF.start().toXML() == null) {
                    setStatus(Status.SERVER_ERROR_BAD_GATEWAY);
                    errors.add(new ResourceError("Can not handle request due to response null"));
                } else {
                    connexion = database.getNewConnection();
                    connexion.setAutoCommit(false);
                    QueryRunner qR = new QueryRunner();
                    Integer result = qR.update(connexion, sqlPromotion, nom, url);
                    if (result == null || result < 1) {
                        setStatus(Status.SERVER_ERROR_INTERNAL);
                        DbUtils.rollbackAndCloseQuietly(connexion);
                        errors.add(new ResourceError("Can not handle request"));
                    } else {
                        Promotion p = new Promotion();
                        p.setUri(getRootRef().getHostIdentifier() + "/promotions/" + promotion.getIdGroupe());
                        response = p.toXML();
                        connexion.commit();
                    }
                }
            }
            connexion.close();
        } catch (SQLException e) {
            DbUtils.rollbackAndCloseQuietly(connexion);
            throw e;
        }
        if (!errors.isEmpty()) {
            response = ResourceError.getListRepresentation(errors);
        }
        return response;
    }

    @Delete
    public void doDelete() throws Exception {
        final String sqlGroupe = "DELETE FROM groupe WHERE id_groupe = " + promotion.getIdGroupe() + " AND url IS NOT NULL";

        Connection connexion = null;
        try {
            connexion = database.getNewConnection();
            connexion.setAutoCommit(false);
            QueryRunner queryRunner = new QueryRunner();

            int res = queryRunner.update(connexion, sqlGroupe);
            if (res < 1) {
                DbUtils.rollbackAndCloseQuietly(connexion);
                setStatus(Status.SERVER_ERROR_INTERNAL, "Impossible de supprimer la ressource représentant cete promotion");
            } else {
                connexion.commit();
                DbUtils.closeQuietly(connexion);
                setStatus(Status.SUCCESS_NO_CONTENT);
            }

        } catch (SQLException e) {
            DbUtils.rollbackAndCloseQuietly(connexion);
            throw e;
        }
    }

    @SuppressWarnings("unchecked")
    private xml.form.Form getNewForm(Representation entity) {
        xml.form.Form form = new xml.form.Form(entity);
        NotEmptyValidator notEmptyValidator = new NotEmptyValidator();
        form.addValidators("nomPromotion", notEmptyValidator, new LengthValidator(255));
        form.addValidators("uriPromotion", notEmptyValidator, new URIValidator());
        return form;
    }

    @Override
    protected void doCatch(Throwable throwable) {
        super.doCatch(throwable);
        throwable.printStackTrace();
    }
}
